package www.dianbaozu.com.extension

import com.netease.nim.uikit.api.NIMHelper
import com.netease.nimlib.sdk.RequestCallback
import com.netease.nimlib.sdk.auth.LoginInfo
import com.orhanobut.logger.Logger
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch
import www.dianbaozu.com.R
import www.wen.com.common.lib.base.module.BaseApiViewModel
import www.wen.com.common.lib.data.entities.*
import www.wen.com.common.lib.data.repository.AppDataManager
import www.wen.com.common.lib.extension.getString
import java.util.concurrent.CountDownLatch

/**
 * @author WEN
 * @Description:
 * @date 2021/9/13 15:33
 */

@Throws(Exception::class)
fun AppDataManager.nimFlow(account: String, token: String, action: (() -> Unit)? = null): Flow<Result<LoginInfo>?> {
    return flow {
        var result: Result<LoginInfo>? = null
        val latch = CountDownLatch(1)
        var isLoginSuccess = false
        NIMHelper.login(
                account,
                token,
                object : RequestCallback<LoginInfo?> {
                    override fun onSuccess(param: LoginInfo?) {
                        NIMHelper.loginSuccessInit(param?.account)
                        result = Result.Success(param!!)
                        isLoginSuccess = true
                        latch.countDown()
                    }

                    override fun onFailed(code: Int) {
                        Logger.i("云信登录失败-> 错误代码:$code")
                        isLoginSuccess = false
                        latch.countDown()
                    }

                    override fun onException(exception: Throwable?) {
                        isLoginSuccess = false
                        latch.countDown()
                    }

                })
        latch.await()
        if(!isLoginSuccess){
            throw Exception("登录失败")
        }
        action?.invoke()
        emit(result)
    }.flowOn(context = Dispatchers.IO)
}

fun BaseApiViewModel.requestServerDetails(viewModelScope: CoroutineScope, serverId: String, action: (ServerInfo) -> Unit) {
    viewModelScope.launch {
        loading.value = UiStateCustom(
                stateData = LoadingDialog(
                        getString(www.wen.com.common.R.string.loading),
                        LoadingDialogStateType.LOADING
                )
        )
        val result = appDataManager.requestServerDetails(serverId)
        if (result is Result.Success) {
            loading.value = UiStateCustom(
                    stateData = LoadingDialog(
                            tip = "",
                            loadingDialogStateType = LoadingDialogStateType.SUCCESS,
                            isShowDialogTip = false,
                            isShowToastTip = false,
                    )
            )
            action.invoke(result.data)
        } else if (result is Result.Error) {
            loading.value = UiStateCustom(
                    stateData = LoadingDialog(
                            tip = result.exception.message ?: getString(R.string.com_loading_failed),
                            loadingDialogStateType = LoadingDialogStateType.ERROR,
                            isShowDialogTip = false,
                            isShowToastTip = true
                    )
            )
        }
    }
}


fun <T> BaseApiViewModel.requestUniversally(
        viewModelScope: CoroutineScope,
        request: suspend (appDataManager: AppDataManager) -> Result<T>,
        tipLoading: String = getString(R.string.loading),
        tipSuccess: String = getString(R.string.loading_succeeded),
        tipFail: String = getString(R.string.network_anomaly),
        isShowDialogTip: Boolean = false,
        isShowToastTip: Boolean = true,
        isShowErrorDialogTip: Boolean = false,
        isShowErrorToastTip: Boolean = true,
        resultFailCall: ((String) -> Unit)? = null,
        resultCall: ((T) -> Unit)? = null,
) {
    viewModelScope.launch {
        loading.value = UiStateCustom(
                stateData = LoadingDialog(
                        tipLoading,
                        LoadingDialogStateType.LOADING
                )
        )
        val result = request.invoke(appDataManager)
        if (result is Result.Success) {
            loading.value = UiStateCustom(
                    stateData = LoadingDialog(
                            tip = tipSuccess,
                            loadingDialogStateType = LoadingDialogStateType.SUCCESS,
                            isShowDialogTip = isShowDialogTip,
                            isShowToastTip = isShowToastTip,
                    )
            )
            resultCall?.invoke(result.data)
        } else if (result is Result.Error) {
            loading.value = UiStateCustom(
                    stateData = LoadingDialog(
                            tip = result.exception.message ?: tipFail,
                            loadingDialogStateType = LoadingDialogStateType.ERROR,
                            isShowDialogTip = isShowErrorDialogTip,
                            isShowToastTip = isShowErrorToastTip,
                    )
            )
            resultFailCall?.invoke(result.exception.message ?: tipFail)
        }
    }
}

